/*
 * ESPRESSIF MIT License
 *
 * Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
 *
 * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
 * it is free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_http_client.h"
#include "sdkconfig.h"
#include "audio_common.h"
#include "audio_hal.h"
#include "ai_chat.h"
#include "cJSON.h"

static const char *TAG = "AI_CHAT"; // 日志标签更改时需要修改 MINIMAX_CHAT

// 定义 SAFE_FREE 宏
#define SAFE_FREE(ptr)   \
    do                   \
    {                    \
        if (ptr != NULL) \
        {                \
            free(ptr);   \
            ptr = NULL;  \
        }                \
    } while (0)

// 定义 AIchat_key 变量
extern const char * AIchat_key; // 这里替换成自己的minimax_key，在main.c中定义

/* #define POST_DATA    "{\
\"model\":\"abab5.5s-chat\",\"tokens_to_generate\": 256,\"temperature\":0.7,\"top_p\":0.7,\"plugins\":[],\"sample_messages\":[],\
\"reply_constraints\":{\"sender_type\":\"BOT\",\"sender_name\":\"小新\"},\
\"bot_setting\":[{\
\"bot_name\":\"小新\",\
\"content\":\"小新，性别女，年龄22岁，知性大姐，性格活泼可爱，说话幽默风趣，喜欢美食，爱好旅行，言简意赅。\\n\"}],\
\"messages\":[{\"sender_type\":\"USER\",\"sender_name\":\"靓仔\",\"text\":\"%s\"}]\
}" */

#define POST_DATA "{\
\"model\":\"deepseek-chat\",\
\"messages\":[\
{\"role\":\"system\",\"content\":\"You are a helpful assistant.\"},\
{\"role\":\"user\",\"content\":\"%s\"}\
],\
\"stream\":false\
}"

#define MAX_CHAT_BUFFER (2048)
char AIchat_content[2048] = {0};

char *AI_chat(const char *text)  // 这里替换成自己的minimax_chat函数名为AI-chat
{
    char *response_text = NULL;
    char *post_buffer = NULL;
    char *data_buf = NULL;

    esp_http_client_config_t config = {
        //.url = "https://api.minimax.chat/v1/text/chatcompletion_pro?GroupId=1879174093366902935",  // 这里替换成自己的GroupId
        .url = "https://api.deepseek.com/chat/completions", // 替换为 DeepSeek 的 API URL
        .buffer_size_tx = 1024                                 // 默认是512 minimax_key很长 512不够 这里改成1024
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);

    int post_len = asprintf(&post_buffer, POST_DATA, text);

    // 构造 POST 请求体
    if (post_buffer == NULL)
    {
        ESP_LOGE(TAG, "分配 POST 缓冲区失败");
        goto cleanup;
    }

    // 设置 HTTP 请求方法和头部
    esp_http_client_set_method(client, HTTP_METHOD_POST);
    esp_http_client_set_header(client, "Content-Type", "application/json");
    esp_http_client_set_header(client, "Authorization", AIchat_key);

    // 打开连接并发送请求
    if (esp_http_client_open(client, post_len) != ESP_OK)
    {
        ESP_LOGE(TAG, "打开连接时出错");
        goto cleanup; // go to 退出翻译器？
    }
    // 发送 POST 请求体
    int write_len = esp_http_client_write(client, post_buffer, post_len);
    ESP_LOGI(TAG, "需要写入 %d 字节, 实际写入 %d 字节", post_len, write_len);

    // 读取响应数据
    int data_length = esp_http_client_fetch_headers(client);
    if (data_length <= 0)
    {
        data_length = MAX_CHAT_BUFFER;
    }
    data_buf = malloc(data_length + 1);
    if (data_buf == NULL)
    {
        ESP_LOGE(TAG, "分配数据缓冲区失败");
        goto cleanup;
    }
    data_buf[data_length] = '\0';
    int rlen = esp_http_client_read(client, data_buf, data_length);
    data_buf[rlen] = '\0';
    ESP_LOGI(TAG, "响应内容: %s", data_buf);

    /*     // 解析 JSON 数据
        cJSON *root = cJSON_Parse(data_buf);
        int created = cJSON_GetObjectItem(root,"created")->valueint;
        if(created != 0)
        {
            char *reply = cJSON_GetObjectItem(root,"reply")->valuestring;
            strcpy(minimax_content, reply);
            response_text = minimax_content;
            ESP_LOGI(TAG, "response_text:%s", response_text);
        } */

    // 解析响应 JSON
    cJSON *root = cJSON_Parse(data_buf);
    if (root == NULL)
    {
        ESP_LOGE(TAG, "解析 JSON 响应失败");
        goto cleanup;
    }

    // 提取生成的回复
    cJSON *choices = cJSON_GetObjectItem(root, "choices");
    if (choices != NULL && cJSON_IsArray(choices))
    {
        cJSON *first_choice = cJSON_GetArrayItem(choices, 0);
        if (first_choice != NULL)
        {
            cJSON *message = cJSON_GetObjectItem(first_choice, "message");
            if (message != NULL)
            {
                cJSON *content = cJSON_GetObjectItem(message, "content");
                if (content != NULL && cJSON_IsString(content))
                {
                    strncpy(AIchat_content, content->valuestring, MAX_CHAT_BUFFER - 1);
                    AIchat_content[MAX_CHAT_BUFFER - 1] = '\0'; // 确保字符串终止
                    response_text = AIchat_content;
                    ESP_LOGI(TAG, "生成的回复: %s", response_text);
                }
            }
        }
    }

    // 清理 JSON 对象
    cJSON_Delete(root);

cleanup:
    // 使用 SAFE_FREE 宏释放资源
    SAFE_FREE(post_buffer);
    SAFE_FREE(data_buf);
    esp_http_client_cleanup(client);

    return response_text;
}
